package com.ogawa.a7517.fragment;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.net.wifi.ScanResult;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.TextView;

import com.easepal.project.uikit.util.HexUtil;
import com.easepal.softaplib.BioClient;
import com.easepal.softaplib.IConnectListener;
import com.easepal.softaplib.wifi.OnWifiConnectListener;
import com.easepal.softaplib.wifi.SecurityModeEnum;
import com.easepal.softaplib.wifi.WiFiManager;
import com.example.reslib.utils.PreferenceWrapper;
import com.example.reslib.utils.ToastUtils;
import com.example.reslib.view.SoftApPopwindow;
import com.example.reslib.view.SoftApPopwindowAdapter;
import com.example.reslib.view.kprogresshud.KProgressHUD;
import com.ogawa.a7517.Constant;
import com.ogawa.a7517.DataManager;
import com.ogawa.a7517.R;
import com.ogawa.a7517.widget.NetConfigStateDialog;
import com.ogawa.networklib.RetrofitManager;
import com.ogawa.networklib.RxObserver;
import com.ogawa.networklib.networkBean.BaseResponseBean;
import com.ogawa.networklib.networkBean.DeviceStatusBean;
import com.yanzhenjie.permission.AndPermission;

import java.util.ArrayList;

public class WifiNetFragment extends BaseFragment implements View.OnClickListener
        , SoftApPopwindowAdapter.OnItemClickListener {
    private Dialog autoLinkDialog;
    private NetConfigStateDialog stateDialog;
    private SoftApPopwindow softApPopwindow;
    private boolean isSuccess;//热点是否连接成功
    private boolean isWifiFail;//连接可用wifi失败
    private boolean isConnectingWifi;//连接可用wifi是否成功
    private boolean isNetSuccess;//配网是否成功
    private BioClient bioClient;
    private int socketRetryCount;
    private boolean isConnectingSocket;
    private EditText etWifiPsw;
    private TextView tvWifiName;
    private ScanResult scanResult;
    private String wifiPsw;
    private String deviceMac;
    private int wifiRetryCount;
    private boolean isScanning;
    private boolean isConnectScan;//是否是连接热点的扫描
    private boolean firstScan = true;//是否首次扫描
    private boolean scanPotSuccess;//扫描热点是否成功
    private KProgressHUD waitProgress;// 等待进度条

    private static final String DEVICE_AP_IP = "10.10.100.1";
    private static final int DEVICE_AP_PORT = 5000;
    private static final int WIFI_CONNECT_TIMEOUT = 1;// 热点连接超时
    //    private static final int CONNECT_SOCKET_TIMEOUT = 2;// 连接socket超时
    private static final int CONNECT_NET_TIMEOUT = 3;// 配网超时
    private static final long WIFI_CONNECT_TIMEOUT_TIME = 10000L; // 热点连接超时时长
    private static final long SN_TIMEOUT_TIME = 60000L; // 读取Sn码超时时长
    private static final int SCAN_WIFI_FAIL = 4;//扫描热点失败
    private static final int RESCAN_WIFI = 5;//重新扫描热点

    private static final long SCAN_WIFI_TIME_OUT = 20000L;//扫描热点失败超时时间
    private boolean getSnFail;

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case WIFI_CONNECT_TIMEOUT:
                    showStateDialog(R.string.connect_device_spot_fail, R.string.connect_device_spot_fail_tip, false);
                    break;
//                case CONNECT_SOCKET_TIMEOUT:
//                    showStateDialog(R.string.net_connect_fail, R.string.socket_connect_fail_tip, false);
//                    break;
                case CONNECT_NET_TIMEOUT:
                    removeCallbacksAndMessages(null);
                    isSuccess = false;
                    getSnFail = true;
                    showStateDialog(R.string.net_connect_fail, R.string.net_connect_fail_tip, false);
                    break;
                case RESCAN_WIFI:
                    scanWifi(true);
                    break;
                case SCAN_WIFI_FAIL:
                    removeMessages(RESCAN_WIFI);
                    connectDevice();
                    break;
            }
        }
    };

    private IConnectListener connectListener = new IConnectListener() {
        @Override
        public void onConnectionSuccess() {
            if (isConnectingSocket) {
                isConnectingSocket = false;
                setDeviceNetwork();
            }
        }

        @Override
        public void onConnectionFailed() {
            if (isConnectingSocket) {
                if (socketRetryCount > 0) {
                    socketRetryCount--;
                    bioClient.reconnect();
                } else {
                    isConnectingSocket = false;
                    mHandler.sendEmptyMessage(CONNECT_NET_TIMEOUT);
                }
            } else {
                mHandler.sendEmptyMessage(CONNECT_NET_TIMEOUT);
            }
        }

        @Override
        public void onMessage(byte[] bytes) {
            if (bytes != null) {
                parseMessage(bytes);
            }
        }
    };

    @Override
    public int getLayoutId() {
        return R.layout.fragment_net_connect;
    }

    @Override
    public void onStart() {
        super.onStart();
        setTitle("");
    }

    @Override
    public void initView(View view) {
        view.findViewById(R.id.iv_confirm).setOnClickListener(this);
        view.findViewById(R.id.iv_refresh).setOnClickListener(this);
        tvWifiName = view.findViewById(R.id.tv_wifi_name);
        tvWifiName.setOnClickListener(this);
        etWifiPsw = view.findViewById(R.id.et_wifi_psw);
        WiFiManager.getInstance(activity7517).registerBroadcastReceivers(activity7517);
        WiFiManager.getInstance(activity7517).setOnWifiEnabledListener(enabled -> {
            if (enabled) {//开启
                showAutoLinkDialog();
            } else {
                isSuccess = false;
            }
        });
        WiFiManager.getInstance(activity7517).setOnWifiScanResultsListener(scanResults -> {
            isScanning = false;
            softApPopwindow.update(scanResults);
            if (!isConnectScan) {
                cancelWaitingDialog();
            }
            if (isConnectScan && !isSuccess && !scanPotSuccess) {
                if (firstScan) {
                    mHandler.sendEmptyMessageDelayed(SCAN_WIFI_FAIL, SCAN_WIFI_TIME_OUT);
                }
                for (ScanResult scanResult : scanResults) {
                    if (scanResult.SSID.equals(Constant.AUTO_LINK_SSID)) {
                        scanPotSuccess = true;
                        break;
                    }
                }
                if (scanPotSuccess) {
                    firstScan = true;
                    mHandler.removeMessages(SCAN_WIFI_FAIL);
                    connectDevice();
                } else {
                    firstScan = false;
                    mHandler.sendEmptyMessageDelayed(RESCAN_WIFI, 1000);
                }
            }
        });
        setWifiListener();
        if (WiFiManager.getInstance(activity7517).isWifiEnabled()) {
            WiFiManager.getInstance(activity7517).startScan();
            showAutoLinkDialog();
        } else {
            ToastUtils.showShortToast(activity7517, activity7517.getString(R.string.open_wifi_tip));
        }
        waitProgress = KProgressHUD.create(getActivity()).setStyle(KProgressHUD.Style.SPIN_INDETERMINATE);
        softApPopwindow = new SoftApPopwindow(activity7517, new ArrayList<>(), this);
    }

    private void scanWifi(boolean flag) {
        isConnectScan = flag;
        AndPermission.with(this)
                .runtime()
                .permission(Manifest.permission.ACCESS_COARSE_LOCATION)
                .onGranted(data -> {
                    if (!isScanning) {
                        isScanning = true;
                        WiFiManager.getInstance(activity7517).startScan();
                        if (!flag) {
                            showWaitDialog(R.string.waiting);
                        }
                    }
                })
                .onDenied(data -> {
                })
                .start();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.tv_wifi_name) {
            if (softApPopwindow.getData() == null || softApPopwindow.getData().size() == 0) {
                scanWifi(false);
            }
            softApPopwindow.setWidth(tvWifiName.getWidth());
            softApPopwindow.showPopupWindow(tvWifiName);
        } else if (id == R.id.iv_confirm) {
            if (isSuccess && scanResult != null) {
                wifiPsw = etWifiPsw.getText().toString();
                if (wifiPsw.length() != 0 && (wifiPsw.length() < 8 || wifiPsw.length() > 32)) {
                    ToastUtils.showShortToast(activity7517, activity7517.getString(R.string.wifi_psw_error));
                    return;
                }
                if (isWifiFail) {
                    connectRouter();
                } else {
                    getSnFail = false;
                    connectSocket();
                }
                activity7517.showWaitDialog(R.string.waiting);
            }
        } else if (id == R.id.iv_refresh) {
            scanWifi(false);
        }
    }

    /**
     * 显示自动连接的弹窗
     */
    private void showAutoLinkDialog() {
        firstScan = true;
        scanPotSuccess = false;
        if (autoLinkDialog == null) {
            autoLinkDialog = new Dialog(activity7517);
            autoLinkDialog.getWindow().addFlags(Window.FEATURE_NO_TITLE);
            autoLinkDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
            autoLinkDialog.setContentView(R.layout.dialog_autolink);
            autoLinkDialog.setCancelable(false);
            autoLinkDialog.findViewById(R.id.tv_dialog_confirm).setOnClickListener(v -> {
                String currentSSID = WiFiManager.getInstance(activity7517).getConnectionInfo()
                        .getSSID().replaceAll("\"", "");
                if (Constant.AUTO_LINK_SSID.equals(currentSSID)) {
                    isSuccess = true;
                    showStateDialog(R.string.connect_device_spot_success, R.string.connect_wifi_tip, true);
                } else {
                    showWaitDialog(R.string.waiting);
                    scanWifi(true);
                }
                autoLinkDialog.dismiss();
            });
            autoLinkDialog.findViewById(R.id.tv_dialog_cancel).setOnClickListener(view -> {
                autoLinkDialog.dismiss();
                activity7517.popBackStack();
            });
        }
        autoLinkDialog.show();
    }

    /**
     * 连接设备热点
     */
    private void connectDevice() {
        WiFiManager.getInstance(activity7517).connectOpenNetwork(Constant.AUTO_LINK_SSID);
        showWaitDialog(R.string.waiting);
        mHandler.sendEmptyMessageDelayed(WIFI_CONNECT_TIMEOUT, WIFI_CONNECT_TIMEOUT_TIME);
    }

    private void setWifiListener() {
        WiFiManager.getInstance(activity7517).setOnWifiConnectListener(new OnWifiConnectListener() {
            @Override
            public void onWiFiPreConnect(boolean isFinished) {

            }

            @Override
            public void onWiFiConnectSuccess(String SSID) {
                if (SSID != null) {
                    String ssid = SSID.replaceAll("\"", "");
                    if (!isSuccess && Constant.AUTO_LINK_SSID.equals(ssid)) {//连接设备热点成功
                        mHandler.removeMessages(WIFI_CONNECT_TIMEOUT);
                        isSuccess = true;
                        showStateDialog(R.string.connect_device_spot_success, R.string.connect_wifi_tip, true);
                        if (autoLinkDialog != null && autoLinkDialog.isShowing()) {
                            autoLinkDialog.dismiss();
                        }
                    }
                    if (isSuccess && isConnectingWifi) {
                        if (scanResult != null && ssid.equals(scanResult.SSID)) {//连接可用网络成功
                            isConnectingWifi = false;
                            isWifiFail = false;
                            getSn();
                            mHandler.sendEmptyMessageDelayed(CONNECT_NET_TIMEOUT, SN_TIMEOUT_TIME);
                        } else {
                            if (wifiRetryCount > 0) {
                                wifiRetryCount--;
                                connectAp(scanResult, wifiPsw);
                            } else {
                                isWifiFail = true;
                                mHandler.sendEmptyMessage(CONNECT_NET_TIMEOUT);
                            }
                        }
                    }
                }
            }

            @Override
            public void onWiFiConnectFailure(String SSID) {//连接设备热点失败
                if (!isSuccess) {
                    mHandler.removeMessages(WIFI_CONNECT_TIMEOUT);
                    showStateDialog(R.string.connect_device_spot_fail, R.string.connect_device_spot_fail_tip, false);
                } else {
                    mHandler.sendEmptyMessage(CONNECT_NET_TIMEOUT);
                }
            }
        });
    }

    /**
     * 显示配网结果弹窗
     *
     * @param tip1
     * @param tip2
     * @param success
     */
    private void showStateDialog(int tip1, int tip2, boolean success) {
        cancelWaitingDialog();
        if (stateDialog == null) {
            stateDialog = new NetConfigStateDialog(activity7517);
            stateDialog.setOnConfirmClickListener(v -> {
                cancelWaitingDialog();
                if (!isSuccess) {
                    connectDevice();
                }
                stateDialog.dismiss();
                if (isNetSuccess) {
                    activity7517.popBackStack(MainFragment.class.getName(), 0);
                }
            });
        }
        stateDialog.setTipOne(activity7517.getString(tip1));
        stateDialog.setTipTwo(activity7517.getString(tip2));
        stateDialog.setTipImg(success ? R.drawable.img_net_success : R.drawable.img_net_fail);
        stateDialog.show();
    }

    /**
     * 建立socket连接
     */
    private void connectSocket() {
        closeSocket();
        newSocket();
        if (!isConnectingSocket) {
            deviceMac = null;
            isConnectingSocket = true;
            bioClient.connect();
            socketRetryCount = 3;
        }
    }

    /**
     * 发送WIFI账号密码至设备
     * ','使用'\,'表示，'$'使用'\$'表示，'\'使用'\\'表示。AT指令中作为参数分隔符的','、'$'不进行转义
     */
    private void setDeviceNetwork() {
        String wifiName = scanResult.SSID;
        String ssid = wifiName;
        String mpsw = wifiPsw;
        ssid = ssid.replace("\\", "\\\\");
        ssid = ssid.replace(",", "\\,");
        ssid = ssid.replace("$", "\\$");

        mpsw = mpsw.replace("\\", "\\\\");
        mpsw = mpsw.replace(",", "\\,");
        mpsw = mpsw.replace("$", "\\$");
        String msg = "AT+SETWLAN=" + ssid + "," + mpsw + "$";
        bioClient.sendMsg(msg);
    }

    /**
     * 解析设备发来的信息
     *
     * @param bytes 字节数组
     */
    private void parseMessage(byte[] bytes) {
        String s = new String(bytes);

        if (s.contains("OK")) {//获取mac地址
            if (TextUtils.isEmpty(deviceMac)) {
                String msg = "AT+GETMAC";
                bioClient.sendMsg(msg);
            } else {
                connectRouter();
            }
        } else {
            String mac = HexUtil.byte2Hex(bytes);
            if (null != mac && mac.length() == 12) {
                deviceMac = mac.toUpperCase();
                connectRouter();
            }
        }
    }

    /**
     * 连接路由器（可联网的WIFI）
     */
    private void connectRouter() {
        isConnectingWifi = true;
        closeSocket();
        wifiRetryCount = 3;
        connectAp(scanResult, wifiPsw);
    }

    /**
     * 连接指定热点
     *
     * @param scanResult ScanResult对象
     * @param psw        密码
     * @return true-连接开始/false-连接失败
     */
    private boolean connectAp(ScanResult scanResult, String psw) {
        if (null == scanResult) return false;
        SecurityModeEnum securityModeEnum = WiFiManager.getInstance(activity7517).getSecurityMode(scanResult);
        switch (securityModeEnum) {
            case WPA:
            case WPA2:
                WiFiManager.getInstance(activity7517).connectWPA2Network(scanResult.SSID, psw);
                break;
            case WEP:
                WiFiManager.getInstance(activity7517).connectWEPNetwork(scanResult.SSID, psw);
                break;
            case OPEN: // 开放网络
                WiFiManager.getInstance(activity7517).connectOpenNetwork(scanResult.SSID);
                break;
        }
        return true;
    }

    /**
     * 关闭Socket连接
     */
    private void closeSocket() {
        if (bioClient != null) {
            bioClient.disconnect();
            bioClient = null;
        }
    }

    /**
     * 新建Socket客户端对象
     */
    private void newSocket() {
        if (bioClient == null) {
            bioClient = new BioClient(connectListener);
            bioClient.setConnectAddress(DEVICE_AP_IP, DEVICE_AP_PORT);
        }
    }

    private void getSn() {
        if (TextUtils.isEmpty(deviceMac)) {
            mHandler.sendEmptyMessage(CONNECT_NET_TIMEOUT);
            return;
        }
        showWaitDialog(R.string.waiting);
        RetrofitManager instance = RetrofitManager.getInstance();
        instance.getData(instance.getApiService().getDeviceStatus(deviceMac, 1)
                , new RxObserver<BaseResponseBean<DeviceStatusBean>>(activity7517, false) {
                    @Override
                    public void onSuccess(BaseResponseBean<DeviceStatusBean> responseBean) {
                        mHandler.removeMessages(CONNECT_NET_TIMEOUT);
                        isNetSuccess = true;
                        //保存按摩椅sn码
                        new PreferenceWrapper().setStringValueAndCommit(Constant.SN_7517, responseBean.getData().getSn());
                        DataManager.getInst().setSnChange(true);
                        showStateDialog(R.string.net_connect_success, R.string.net_connect_success_tip, true);
                    }

                    @Override
                    public void onError(String errMsg) {
                        if (!getSnFail) {
                            mHandler.postDelayed(() -> getSn(), 2000);
                        } else {
                            cancelWaitingDialog();
                        }
                    }
                }, this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
        WiFiManager.getInstance(activity7517).onDestory(activity7517);
    }

    @Override
    public void onItemClick(ScanResult scanResult) {
        this.scanResult = scanResult;
        softApPopwindow.dimissPopupWindow();
        tvWifiName.setText(scanResult.SSID);
    }

    /**
     * 显示等待对话框
     *
     * @param strRes
     */
    private void showWaitDialog(int strRes) {
        if (null != waitProgress) {
            if (strRes != 0) {
                waitProgress.setLabel(activity7517.getString(strRes));
            } else {
                waitProgress.setLabel("");
            }
            if (!waitProgress.isShowing()) {
                waitProgress.show();
            }
        }
    }

    /**
     * 取消等待对话框
     */
    private void cancelWaitingDialog() {
        activity7517.cancelWaitingDialog();
        if (null != waitProgress && waitProgress.isShowing()) {
            waitProgress.dismiss();
        }
    }
}
